import { Sequelize, QueryTypes } from 'sequelize';
import * as fs from 'fs';
import * as path from 'path';

interface DatabaseConfig {
  host: string;
  port: number;
  database: string;
  username: string;
  password: string;
  dialect: 'mysql';
  pool: {
    max: number;
    min: number;
    acquire: number;
    idle: number;
  };
  dialectOptions: {
    charset: string;
  };
}

class DatabaseConnection {
  private sequelize: Sequelize | null = null;
  private config!: DatabaseConfig;

  constructor() {
    this.loadConfig();
  }

  private loadConfig(): void {
    try {
      const configPath = path.join(process.cwd(), 'config', 'database.json');
      const configFile = fs.readFileSync(configPath, 'utf8');
      const configs = JSON.parse(configFile);
      
      const env = process.env.NODE_ENV || 'development';
      this.config = configs[env];
      
      if (!this.config) {
        throw new Error(`Database configuration for environment '${env}' not found`);
      }
    } catch (error) {
      console.error('Failed to load database configuration:', error);
      throw error;
    }
  }

  async connect(): Promise<Sequelize> {
    if (this.sequelize) {
      return this.sequelize;
    }

    try {
      this.sequelize = new Sequelize({
        host: this.config.host,
        port: this.config.port,
        database: this.config.database,
        username: this.config.username,
        password: this.config.password,
        dialect: this.config.dialect,
        pool: this.config.pool,
        dialectOptions: this.config.dialectOptions,
        logging: process.env.NODE_ENV === 'development' ? console.log : false,
        define: {
          timestamps: true,
          underscored: false,
          freezeTableName: true,
        },
      });

      // 测试连接
      await this.sequelize.authenticate();
      console.log('✅ Database connection established successfully');
      
      return this.sequelize;
    } catch (error) {
      console.error('❌ Unable to connect to database:', error);
      throw error;
    }
  }

  async disconnect(): Promise<void> {
    if (this.sequelize) {
      await this.sequelize.close();
      this.sequelize = null;
      console.log('📊 Database connection closed');
    }
  }

  getSequelize(): Sequelize {
    if (!this.sequelize) {
      throw new Error('Database connection not established. Call connect() first.');
    }
    return this.sequelize;
  }

  async isConnected(): Promise<boolean> {
    if (!this.sequelize) {
      return false;
    }
    
    try {
      await this.sequelize.authenticate();
      return true;
    } catch {
      return false;
    }
  }

  async executeRawQuery(sql: string, replacements?: any[]): Promise<any> {
    const sequelize = this.getSequelize();
    return await sequelize.query(sql, {
      replacements,
      type: QueryTypes.SELECT,
    });
  }

  async healthCheck(): Promise<{ status: 'healthy' | 'unhealthy'; details: any }> {
    try {
      const startTime = Date.now();
      await this.sequelize?.authenticate();
      const responseTime = Date.now() - startTime;
      
      return {
        status: 'healthy',
        details: {
          responseTime,
          database: this.config.database,
          host: this.config.host,
          port: this.config.port,
        },
      };
    } catch (error) {
      return {
        status: 'unhealthy',
        details: {
          error: error instanceof Error ? error.message : String(error),
          database: this.config.database,
          host: this.config.host,
          port: this.config.port,
        },
      };
    }
  }
}

// 单例实例
const dbConnection = new DatabaseConnection();

export { dbConnection as DatabaseConnection };
export type { DatabaseConfig };
export type { DatabaseConnection as DatabaseConnectionType };